package net.jcip.chapter5;

import java.util.*;

import net.jcip.annotations.*;

/**
 * HiddenIterator
 * <p/>
 * Iteration hidden within string concatenation
 * <p>
 * addTenThings方法可能会抛出ConcurrentModificationException,因为在生成调试消息的过程中，toString对容器进行迭代。
 * 当然，真正的问题在于 HiddenIterator 不是线程安全的。
 * 在使用println中的set之前必须首先获取HiddenIterator的锁，但在调试代码和日志代码中通常会忽视这个要求。
 *
 * @author Brian Goetz and Tim Peierls
 */
class HiddenIterator {

    @GuardedBy("this")
    private final Set<Integer> set = new HashSet<>();

    public synchronized void add(Integer i) {
        set.add(i);
    }

    public synchronized void remove(Integer i) {
        set.remove(i);
    }

    private void addTenThings() {
        Random r = new Random();
        for (int i = 0; i < 10; i++) {

            add(r.nextInt(100));
        }
        //set 的 toString 方法会对容器进行迭代
        System.out.println("INFO  " + Thread.currentThread().getName() + "  added ten elements to " + set);
    }

    /**
     * 验证
     */
    public static void main(String[] args) {

        HiddenIterator hiddenIterator = new HiddenIterator();


        Thread threadA = new Thread(() -> {

            for (int i = 0; i < 10; i++) {
                hiddenIterator.addTenThings();
            }

        }, "线程A");


        Thread threadB = new Thread(() -> {

            for (int i = 0; i < 10; i++) {
                hiddenIterator.addTenThings();
            }

        }, "线程B");

        threadA.start();
        threadB.start();

        Scanner scanner = new Scanner(System.in);
        System.out.println("任意键退出.....");
        scanner.next();

    }


}
